<?php

declare(strict_types=1);

namespace app\sys\controller;

use app\sys\service\SystemMenuService;
use think\admin\Controller;
use think\admin\Exception;
use think\admin\extend\JwtExtend;
use think\admin\model\SysMessage;
use think\admin\model\SysRelation;
use think\admin\model\SysUser;
use think\admin\service\AdminService;
use think\admin\service\CaptchaService;
use think\admin\service\EmailService;
use think\admin\service\SmsService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

/**
 * 用户接口
 * @login true
 * Class UserCenter
 * @package app\auth\controller
 */
class UserCenter extends Controller
{
    /**
     * 登录时获取菜单
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function loginMenu()
    {
        $menus = SystemMenuService::instance()->getMenus(SystemMenuService::instance()->getModuleMenus(), SystemMenuService::instance()->getSpaMenus());
        $this->success('获取成功！', $menus);
    }

    /**
     * 获取手机端菜单
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function loginMobileMenu()
    {
        $menus = SystemMenuService::instance()->getMobileMenus(SystemMenuService::instance()->getMobileModuleMenus());
        $this->success('获取成功！', $menus);
    }

    /**
     * 我的快捷菜单
     * @login true
     * @return void
     */
    public function loginWorkbench()
    {
        $this->success('快捷菜单获取成功！', AdminService::getUser()['extJson']);
    }

    public function getModuleId()
    {
        $this->success('获取成功！', SystemMenuService::instance()->getLastModuleId($this->request->param('lastPath')));
    }


    /**
     * 我的未读站内信
     * @login true
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function loginUnreadMessagePage()
    {
        $ids = SysRelation::mk()->where(['target_id' => AdminService::getUserId()])->where(['category' => 'DEV_MESSAGE_HAS_USER'])->column('object_id');
        $query = SysMessage::mQuery();
        $query->whereIn('id', $ids);
        // 数据列表搜索过滤
        $query->equal('status');
        $query->like('category');
        $lists = $query->order('id ASC')->page(false,false,false);
        sysoplog('用户消息管理', '用户消息分页列表获取成功');
        $this->success('数据获取成功', $lists['list']);
    }

    /**
     * 登录获取我的消息详情
     * @login true
     * @return void
     * @throws DbException
     */
    public function loginUnreadMessageDetail()
    {
        $detail = SysMessage::mk()->where(['id' => $this->request->param('id')])->where(['is_deleted' => 0, 'status' => 0])->findOrEmpty();
        $json = [
            'read' => true,
            'readTime' => date('Y-m-d h:i:s', time())
        ];
        if (!$detail->isEmpty()) {
            SysRelation::mk()
                ->where(['target_id' => AdminService::getUserId()])
                ->where(['category' => 'DEV_MESSAGE_HAS_USER'])
                ->where(['object_id' => $this->request->param('id')])
                ->update(['ext_json' => json_encode($json)]);
        }
        /*
        $receiveInfoList = [];
        $receiveList = SysRelation::mk()->where(['object_id'=>$this->request->param('id')])->where(['category'=>'DEV_MESSAGE_HAS_USER'])->select()->toArray();
        if($receiveList){
            foreach($receiveList as $v){
                $receiveInfoList[] = [
                    'receiveUserId' => $v['targetId'],
                    'receiveUserName' => $this->_getUserName((int)$v['targetId']),
                    'read' => json_decode($v['extJson'],true)['read']
                ];
            }
        }
        $detail['receiveInfoList'] = $receiveInfoList;
        */
        $this->success('获取成功', $detail);
    }

    /**
     * 获取图形验证码
     * @return void
     */
    public function getPicCaptcha()
    {
        $image = CaptchaService::instance()->initialize();
        $captcha = ['image' => $image->getData(), 'uniqid' => $image->getUniqid()];
        $this->success('生成验证码成功', $captcha);
    }

    /**
     * 找回密码图形验证通过后发短信
     * @return void
     * @throws Exception
     */
    public function findPasswordGetPhoneValidCode()
    {
        $data = $this->_vali([
            'phone.mobile' => '手机号格式错误！',
            'phone.require' => '手机号不能为空！',
            'verify.require' => '图形验证码不能为空!',
            'uniqid.require' => '图形验证标识不能为空!',
            'action.require' => '请求方法不能为空'
        ]);
        if (!CaptchaService::instance()->check($data['verify'], $data['uniqid'])) {
            $this->error('图形验证码验证失败，请重新输入!');
        }
        $map = ['phone' => $data['phone'], 'is_deleted' => 0];
        $user = SysUser::mk()->where($map)->findOrEmpty();
        if ($data['action'] !== null) {
            if ($user->isEmpty() && in_array($data['action'], ['login', 'recover'], true)) {
                $this->error('手机号不存在!');
            }
            if (!$user->isEmpty() && $data['action'] === 'register') {
                $this->error('手机号已被注册!');
            }
            if (!in_array($data['action'], ['login', 'recover', 'register'], true)) {
                $this->error('未知请求来源!');
            }
        } else {
            $this->error('未知错误!');
        }
        [$state, $message, $data] = SmsService::instance()->sendVerifyCode($data['phone']);
        $state ? $this->success($message, $data) : $this->error($message, $data);
    }

    /**
     * 找回密码图形验证通过后发邮件
     * @return void
     * @throws Exception
     */
    public function findPasswordGetEmailValidCode()
    {
        $data = $this->_vali([
            'email.email' => '邮箱格式错误！',
            'email.require' => '邮箱不能为空！',
            'verify.require' => '图形验证码不能为空!',
            'uniqid.require' => '图形验证标识不能为空!',
            'action.require' => '请求方法不能为空'
        ]);
        if (!CaptchaService::instance()->check($data['verify'], $data['uniqid'])) {
            $this->error('图形验证码验证失败，请重新输入!');
        }
        $map = ['email' => $data['email'], 'is_deleted' => 0];
        $user = SysUser::mk()->where($map)->findOrEmpty();
        if ($data['action'] !== null) {
            if ($user->isEmpty() && in_array($data['action'], ['login', 'recover'], true)) {
                $this->error('邮箱不存在!');
            }
            if (!$user->isEmpty() && $data['action'] === 'register') {
                $this->error('邮箱已被注册!');
            }
            if (!in_array($data['action'], ['login', 'recover', 'register'], true)) {
                $this->error('未知请求来源!');
            }
        } else {
            $this->error('未知错误!');
        }
        [$state, $message, $data] = EmailService::instance()->sendVerifyCode($data['email']);
        $state ? $this->success($message, $data) : $this->error($message, $data);
    }

    /**
     * 手机号找回密码
     * @return void
     * @throws Exception
     */
    public function findPasswordByPhone()
    {
        $data = $this->_vali([
            'phone.mobile' => '手机号格式错误！',
            'phone.require' => '手机号不能为空！',
            'captcha.require' => '验证码不能为空!',
            'newPassword.require' => '新密码不能为空!'
        ]);
        if (!SmsService::instance()->checkVerifyCode($data['captcha'], $data['phone'])) {
            $this->error('手机短信验证失败！');
        }
        $map = ['phone' => $data['phone'], 'is_deleted' => 0];
        $user = SysUser::mk()->where($map)->findOrEmpty();
        $this->newPasswordWrite($user, $data);
    }

    /**
     * 新密码写入
     * @param $user
     * @param array $data
     * @return void
     */
    public function newPasswordWrite($user, array $data): void
    {
        if ($user->isEmpty()) {
            $this->app->session->set('restPasswordInputSessionError', true);
            $this->error('登录错误，请重重试!');
        }
        if ($user['password'] === $data['newPassword']) {
            $this->app->session->set('restPasswordInputSessionError', true);
            $this->error('新密码与原密码相同，无需重置。');
        }
        $data['password'] = trim($data['newPassword']);
        $data['id'] = $user['id'];
        unset($data['newPassword']);
        unset($data['captcha']);
        $this->app->session->delete('restPasswordInputSessionError');
        SysUser::mSave($data);
    }

    /**
     * 邮箱找回密码
     * @return void
     */
    public function findPasswordByEmail()
    {
        $data = $this->_vali([
            'email.email' => '邮箱格式错误！',
            'email.require' => '邮箱不能为空！',
            'captcha.require' => '验证码不能为空!',
            'newPassword.require' => '新密码不能为空!'
        ]);
        if (!EmailService::instance()->checkVerifyCode($data['captcha'], $data['email'])) {
            $this->error('邮箱验证失败！');
        }
        $map = ['email' => $data['email'], 'is_deleted' => 0];
        $user = SysUser::mk()->where($map)->findOrEmpty();
        $this->newPasswordWrite($user, $data);
    }

    /**
     * 刷新TOKEN
     * @return string
     * @throws Exception
     */
    public function refreshToken(): string
    {
        return JwtExtend::getNewToken($this->request->post('refreshToken'));
    }

    /**
     * 我的消息列表数据处理
     * @param array $data
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    protected function _page_filter(array &$data)
    {
        $messages = SysRelation::mk()->where(['target_id' => AdminService::getUserId()])->where(['category' => 'DEV_MESSAGE_HAS_USER'])->select()->toArray();
        foreach ($data as &$v) {
            foreach ($messages as $msg) {
                if ($msg['objectId'] === (string)$v['id']) {
                    $v['read'] = json_decode($msg['extJson'], true)['read'];
                }
            }
        }
    }

    /**
     * 获取用户名
     * @param int $id
     * @return string
     */
    private function _getUserName(int $id): string
    {
        return SysUser::mk()->where(['id' => $id])->value('name');
    }
}